
import GameInputEvent from "./GameInputEvent";
import { CtrlModeListener, SingleKeyListener, MouseListener, MultiKeyListener, RockerListener } from "./GameInputListeners";
import { InputType, InputTypeTip } from "./InputConfig";
import InputConverter from "./InputConverter";
import InputListenerMgr from "./InputListenerMgr";
/**
 * 游戏键鼠，手柄转换器 
 */
export default class GameInputMgr {
    static getInstance<T extends {}>(this: new () => T): T {
        if (!(<any>this).ins) {
            (<any>this).ins = new this();
        }
        return (<any>this).ins;
    }

    protected keyEvent: GameInputEvent = new GameInputEvent();
    protected mouseEvent: GameInputEvent = new GameInputEvent();
    protected rockerEvent: GameInputEvent = new GameInputEvent();
    protected _converter: InputConverter = new InputConverter();


    //按键监听队列
    protected keyList: InputListenerMgr<SingleKeyListener> = new InputListenerMgr();
    //鼠标监听队列
    protected mouseList: InputListenerMgr<MouseListener> = new InputListenerMgr();
    //遥感监听队列
    protected rockerList: InputListenerMgr<RockerListener> = new InputListenerMgr();
    //多按键监听队列
    protected multyListener: InputListenerMgr<MultiKeyListener> = new InputListenerMgr();
    //键盘鼠标切换状态监听队列
    protected listeners: InputListenerMgr<CtrlModeListener> = new InputListenerMgr();

    //当前平台类型
    protected _type: string = InputType.CC;

    get type() {
        return this._type;
    }

    changeType(t: string) {
        if (this.type != t) {
            this.type = t;
        }
    }

    set type(t: string) {
        this._type = t;
        let list = this.listeners.list
        for (let index = 0; index < list.length; index++) {
            const element = list[index];
            element.onChangeMode(this._type)
        }
    }
    /**
     * 添加模式切换事件监听对象
     * @param listener 监听对象
    */
    public addCtrlModeListener(listener: CtrlModeListener) {
        this.listeners.on(listener)
    }

    /**
     * 删除模式切换事件监听对象
     * @param listener 监听对象
    */
    public removeCtrlModeListener(listener: CtrlModeListener) {
        this.listeners.off(listener)
    }

    getCfgName() {
        return InputTypeTip[this.type]// + '_key'
    }

    get converter() {
        return this._converter;
    }



    getKeyEvent() {
        return this.keyEvent;
    }

    addMultiKeyListener(l: MultiKeyListener) {
        this.multyListener.on(l)
    }

    removeMultiKeyListener(l: MultiKeyListener) {
        this.multyListener.off(l)
    }

    addKeyListener(listener: SingleKeyListener) {
        this.keyList.on(listener)
    }

    removeKeyListener(listener: SingleKeyListener) {
        this.keyList.off(listener)
    }

    addMouseListener(listener: MouseListener) {
        this.mouseList.on(listener)
    }

    removeMouseListener(listener: MouseListener) {
        this.mouseList.off(listener)
    }

    addRockerListener(listener: RockerListener) {
        this.rockerList.on(listener)
    }

    removeRockerListener(listener: RockerListener) {
        this.rockerList.off(listener)
    }

    onKeyBoardPress(platform: string, keyCode: number, pos: any) {
        keyCode = this.converter.getKeyValue(platform, keyCode)
        if (!keyCode) {
            console.warn(' key is undefined ')
            return;
        }
        if (this.keyEvent.isContainKeys(keyCode)) {
            console.warn(' key is have ')
            return;
        }
        // console.log('onKeyBoardPress keyCode  ', keyCode)
        this.keyEvent.keyCode |= keyCode;
        this.keyEvent.pos = pos;
        let list = this.keyList.list;
        for (let index = 0; index < list.length; index++) {
            const element = list[index];
            element.onKeyBoardPress(keyCode, this.keyEvent)
            if (element.isBlockInput()) {
                break;
            }
        }
        let listMulti = this.multyListener.list;
        for (let index = 0; index < listMulti.length; index++) {
            const element = listMulti[index];
            element.onMultiKeyPress(this.keyEvent)
            if (element.isBlockMultiInput()) {
                break;
            }
        }
    }

    onKeyBoardRelease(platform: string, keyCode: number, pos: any) {
        keyCode = this.converter.getKeyValue(platform, keyCode)
        if (!keyCode) {
            console.warn(' key is undefined ')
            return;
        }
        if (!this.keyEvent.isContainKeys(keyCode)) {
            console.warn(' key is not have ')
            return;
        }
        // console.log('onKeyBoardRelease keyCode  ', keyCode)
        this.keyEvent.keyCode &= ~keyCode;
        this.keyEvent.pos = pos;
        let list = this.keyList.list;
        for (let index = 0; index < list.length; index++) {
            const element = list[index];
            element.onKeyBoardRelease(keyCode, this.keyEvent)
            if (element.isBlockInput()) {
                break;
            }
        }

    }
    onMouseMove(platform: string, keyCode: number, pos: any): void {
        keyCode = this.converter.getKeyValue(platform, keyCode)
        if (!keyCode) {
            return;
        }
        let list = this.mouseList.list;
        this.mouseEvent.pos = pos;
        for (let index = 0; index < list.length; index++) {
            const element = list[index];
            element.onMouseMove(keyCode, this.mouseEvent)
            if (element.isBlockMouse()) {
                break;
            }
        }
    }

    onMouseDown(platform: string, keyCode: number, pos: any): void {
        keyCode = this.converter.getKeyValue(platform, keyCode)
        if (!keyCode) {
            return;
        }
        this.mouseEvent.pos = pos;
        this.mouseEvent.keyCode |= keyCode;
        // console.log('onMouseDown keyCode  ', keyCode)
        let list = this.mouseList.list;
        for (let index = 0; index < list.length; index++) {
            const element = list[index];
            element.onMouseDown(keyCode, this.mouseEvent)
            if (element.isBlockMouse()) {
                break;
            }
        }
    }

    onMouseUp(platform: string, keyCode: number, pos: any): void {
        keyCode = this.converter.getKeyValue(platform, keyCode)
        if (!keyCode) {
            return;
        }
        this.mouseEvent.pos = pos;
        this.mouseEvent.keyCode &= ~keyCode;

        // console.log('onMouseUp keyCode  ', keyCode)
        let list = this.mouseList.list;
        for (let index = 0; index < list.length; index++) {
            const element = list[index];
            element.onMouseUp(keyCode, this.mouseEvent)
            if (element.isBlockMouse()) {
                break;
            }
        }
    }


    onRockerEvent(platform: string, keyCode: number, x: number, y: number): void {
        keyCode = this.converter.getKeyValue(platform, keyCode)
        if (!keyCode) {
            return;
        }
        let list = this.rockerList.list;
        this.rockerEvent.keyCode = keyCode;
        this.rockerEvent.pos.set(x, y)
        for (let index = 0; index < list.length; index++) {
            const element = list[index];
            element.onRockerEvent(keyCode, this.rockerEvent)
            if (element.isBlockRocker()) {
                break;
            }
        }
    }
}